package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.feign.ProductFeignApi;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMQResult;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ProductFeignApi productFeignApi;

    @Override
    public List<SeckillProductVo> selectByTime(int time) {
        // 1. 查询 t_seckill_product 表
        List<SeckillProductVo> list = seckillProductMapper.selectByTime(time);

        // 2. 获取其中 productId, 放入 idList 中
        List<Long> idList = list.stream().map(SeckillProductVo::getProductId).collect(Collectors.toList());

        // 3. 用上面的 idList 远程调用 商品服务, 获取商品详情
        Result<List<Product>> listResult = productFeignApi.queryProductByIds(idList);

        // 4. 整合 seckillProductVO
        if (listResult != null && !listResult.hasError()) {
            List<Product> productList = listResult.getData();
            if (productList != null || productList.size() > 0){
                // 双层循环 (小数据量适用)
//                for (Product product : productList) {
//                    for (SeckillProductVo seckillProductVO : list) {
//                        if (product.getId().equals(seckillProductVO.getProductId())){
//                            seckillProductVO.setProductName(product.getProductName());
//                            seckillProductVO.setProductTitle(product.getProductTitle());
//                            seckillProductVO.setProductImg(product.getProductImg());
//                            seckillProductVO.setProductDetail(product.getProductDetail());
//                            seckillProductVO.setProductPrice(product.getProductPrice());
//                        }
//                    }
//                }
                // Map 中间层优化双层循环
                Map<Long, Product> tempMap = productList.stream().collect(Collectors.toMap(Product::getId, product -> product));
                for (Product product : productList) {
                    tempMap.put(product.getId(), product);
                }
                for (SeckillProductVo seckillProductVO : list) {
                    Product product = tempMap.get(seckillProductVO.getProductId());
                    if (product != null){
                        // 考虑简洁性可用, 但是为了性能还是手动 / 使用相关代码生成器
//                        BeanUtils.copyProperties(product, seckillProductVO);
                        seckillProductVO.setProductName(product.getProductName());
                        seckillProductVO.setProductTitle(product.getProductTitle());
                        seckillProductVO.setProductImg(product.getProductImg());
                        seckillProductVO.setProductDetail(product.getProductDetail());
                        seckillProductVO.setProductPrice(product.getProductPrice());
                    }
                }
            }
        }

        return list;
    }

    @Override
    public List<SeckillProductVo> queryByTime(int time) {
        List<Object> values = redisTemplate.opsForHash().values(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(String.valueOf(time)));
        // redis 中没货, 那就是商品未决定好上架
        if (values == null) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_NOT_START);
        }
        return values.stream()
                .map(x -> JSON.parseObject(String.valueOf(x), SeckillProductVo.class))
                .collect(Collectors.toList());
    }

    @Override
    public SeckillProductVo find(int time, Long seckillId) {
        Object o = redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(String.valueOf(time)), String.valueOf(seckillId));
        if (StringUtils.isEmpty(String.valueOf(o))) {
            return null;
        }
        return JSON.parseObject(String.valueOf(o), SeckillProductVo.class);
    }

    @Override
    public void replenishRedisStock(OrderMQResult orderMQResult) {
        Long seckillId = orderMQResult.getSeckillId();
        int stockCount = seckillProductMapper.getStockCount(seckillId);

        // 从mysql中恢复库存
        redisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(String.valueOf(orderMQResult.getTime())), String.valueOf(seckillId), String.valueOf(stockCount));

        // 发送消息,  告诉秒杀服务, 恢复本地标识
        rocketMQTemplate.sendOneWay(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC, seckillId);
    }

}
